Skip to content

Replace glob scan with fs-based traversal in dev routes API - #65

Open
remcostoeten wants to merge 1 commit into
claude/fix-activity-responsive-ghTq5from
codex/fix-build-error-due-to-missing-glob-module
Open

Replace glob scan with fs-based traversal in dev routes API#65
remcostoeten wants to merge 1 commit into
claude/fix-activity-responsive-ghTq5from
codex/fix-build-error-due-to-missing-glob-module

Conversation

@remcostoeten

@remcostoeten remcostoeten commented Feb 16, 2026

Copy link
Copy Markdown
Owner

Motivation

  • The build failed under Turbopack with Module not found: Can't resolve 'glob' for the dev routes API, so the route discovery should avoid requiring the external glob package.
  • The intent is to preserve the route-discovery behavior while removing an external dependency that breaks production builds.

Description

  • Replaced the glob import with readdir from fs/promises and added an internal findPageFiles recursive scanner in src/app/api/dev/routes/route.ts that collects page.{tsx,js,jsx} files.
  • The scanner preserves filtering behavior by skipping api directories and entries that start with . or _, and uses a PAGE_EXTENSIONS set to detect page files.
  • Kept the existing route normalization, label generation (formatRouteLabel), duplicate removal, and sorting logic intact while switching to path.sep for splitting directory segments.

Testing

  • Attempted bun --bun install, but dependency fetches failed with registry 403 errors which prevented installing next and other packages so a full build could not be run.
  • Attempted bun --bun next build, which failed in this environment with Script not found "next" due to missing installed dependencies.
  • Attempted ./node_modules/.bin/next build, which failed with No such file or directory because node_modules was not available in the current environment.

Codex Task

Summary by Sourcery

Enhancements:

  • Introduce a recursive fs-based page file scanner that discovers app route pages while preserving existing filtering rules and route normalization behavior.

Confidence Score: 2/5

  • This PR has a critical logical error that will break route discovery
  • The inverted route group filtering logic will cause all discovered routes to be malformed - route groups like (marketing) will be kept in paths while normal segments may be removed, breaking the entire route discovery feature
  • src/app/api/dev/routes/route.ts requires immediate attention to fix the route group filtering logic

Important Files Changed

Filename Overview
src/app/api/dev/routes/route.ts Replaced glob dependency with fs-based scanner, but route group filtering logic is inverted causing incorrect route paths

Flowchart

flowchart TD
    A[GET /api/dev/routes] --> B{Check Dev Access}
    B -->|Denied| C[Return 401]
    B -->|Allowed| D[Get appDir path]
    D --> E[findPageFiles recursively]
    E --> F{For each entry}
    F --> G{Starts with . or _?}
    G -->|Yes| H[Skip entry]
    G -->|No| I{Is Directory?}
    I -->|Yes| J{Directory name == 'api'?}
    J -->|Yes| H
    J -->|No| K[Recurse into directory]
    K --> F
    I -->|No| L{Is File?}
    L -->|Yes| M{Filename == page.tsx/js/jsx?}
    M -->|Yes| N[Collect file path]
    M -->|No| H
    L -->|No| H
    N --> O[All files collected]
    O --> P[Map to routes]
    P --> Q[Remove dirname and extension]
    Q --> R[Split by path separator]
    R --> S[Filter route groups]
    S --> T[Build route path]
    T --> U[Add label and isDynamic flag]
    U --> V[Remove duplicates]
    V --> W[Sort routes]
    W --> X[Return JSON response]
Loading

Last reviewed commit: 3ee9259

@vercel

vercel Bot commented Feb 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
remcostoeten Error Error Feb 16, 2026 0:13am

@sourcery-ai

sourcery-ai Bot commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Replaces glob-based page discovery in the dev routes API with an internal fs-based recursive scanner while preserving existing route parsing, filtering, and labeling behavior.

Sequence diagram for GET handler using fs-based page discovery

sequenceDiagram
    participant Client
    participant DevRoutesAPI as DevRoutesAPI_GET
    participant FS as FileSystem

    Client->>DevRoutesAPI: HTTP GET /api/dev/routes
    DevRoutesAPI->>DevRoutesAPI: determine cwd and appDir
    DevRoutesAPI->>FS: findPageFiles(appDir)
    activate FS
    FS->>FS: read entries in currentDir
    FS->>FS: recursively traverse subdirectories
    FS->>FS: filter api, .*, _* directories
    FS->>FS: collect page.{tsx,js,jsx} relative paths
    FS-->>DevRoutesAPI: list of page files
    deactivate FS

    DevRoutesAPI->>DevRoutesAPI: map files to route paths
    DevRoutesAPI->>DevRoutesAPI: split dirPath by path.sep
    DevRoutesAPI->>DevRoutesAPI: clean segments and build labels
    DevRoutesAPI->>DevRoutesAPI: remove duplicates and sort routes
    DevRoutesAPI-->>Client: JSON response with discovered routes
Loading

Flow diagram for findPageFiles recursive page scanner

flowchart TD
    A["start findPageFiles(rootDir,currentDir)"] --> B["read directory entries withFileTypes"]
    B --> C["map each entry"]

    C --> D{"entry name startsWith . or _?"}
    D -- yes --> E["return empty list for this entry"]
    D -- no --> F["compute fullPath = join(currentDir,name)<br/>relativePath = relative(rootDir,fullPath)"]

    F --> G{"entry isDirectory?"}
    G -- yes --> H{"entry name === api?"}
    H -- yes --> E
    H -- no --> I["recurse findPageFiles(rootDir,fullPath)<br/>collect returned files"]

    G -- no --> J{"entry isFile?"}
    J -- no --> E
    J -- yes --> K["parsed = path.parse(name)<br/>check parsed.name === page<br/>and ext in PAGE_EXTENSIONS"]

    K --> L{"is page file?"}
    L -- yes --> M["return list containing relativePath"]
    L -- no --> E

    I --> N["flatten lists from all entries"]
    M --> N
    E --> N

    N --> O["return flattened file list"]
    O --> P["end findPageFiles"]
Loading

File-Level Changes

Change Details Files
Replace glob-based page discovery with a recursive fs-based scanner that finds page.{tsx,js,jsx} files under src/app while preserving filtering rules.
  • Introduce PAGE_EXTENSIONS set for allowed page file extensions.
  • Add async findPageFiles(rootDir, currentDir) helper that uses fs.promises.readdir with Dirent objects to recursively traverse directories.
  • Skip entries starting with '.' or '_' and ignore the 'api' directory subtree during traversal.
  • Identify files named 'page' with an allowed extension and return their paths relative to the app root.
  • Flatten collected file lists from recursive calls into a single array of relative paths.
src/app/api/dev/routes/route.ts
Wire the new scanner into the dev routes GET handler and slightly adjust segment splitting to be path-separator aware.
  • Replace glob('**/page.{tsx,js,jsx}', ...) usage with await findPageFiles(appDir).
  • Remove glob-specific ignore options now handled by the custom scanner logic.
  • Change route directory splitting from a regex that handled both separators to using path.sep for platform-aware splitting while keeping downstream normalization and labeling logic unchanged.
src/app/api/dev/routes/route.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/fix-build-error-due-to-missing-glob-module

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 3 comments

Edit Code Review Agent Settings | Greptile


export const dynamic = 'force-dynamic' // Ensure this route is dynamic

const PAGE_EXTENSIONS = new Set(['.tsx', '.js', '.jsx'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing .ts extension - Next.js app router supports page.ts files

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

async function findPageFiles(rootDir: string, currentDir = rootDir): Promise<string[]> {
const entries = await readdir(currentDir, { withFileTypes: true })
const files = await Promise.all(entries.map(async entry => {
if (entry.name.startsWith('.') || entry.name.startsWith('_')) return []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

underscore filtering differs from glob behavior - glob ignored **/_*/** (folders starting with underscore), but this skips any file/folder starting with underscore at any level, potentially missing valid pages in non-underscore folders

@greptile-apps

greptile-apps Bot commented Feb 16, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

src/app/api/dev/routes/route.ts
route group filtering logic is inverted - currently keeps route groups and removes normal segments

            const cleanSegments = segments.filter(segment => {
                // Remove route groups like (marketing)
                return !(segment.startsWith('(') && segment.endsWith(')'))
            }).filter(segment => segment !== '.') // remove . if present

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant